package com.amtf.datafile2.core.std;

import java.util.ArrayList;
import java.util.List;

import com.amtf.datafile2.DataField;
import com.amtf.datafile2.DataFieldDefinition;
import com.amtf.datafile2.DataRecord;
import com.amtf.datafile2.DataTableDefinition;

public abstract class StdDataRecord<T extends DataTableDefinition<?>> implements DataRecord {
	protected T definition = null;
	protected DataField[] fields = null;
	protected List<String> errors = null;

	public StdDataRecord(T definition) {
		this.definition = definition;

		List<? extends DataFieldDefinition> fieldDefs = definition.getFields();
		this.fields = new DataField[fieldDefs.size()];
	}

	public DataField get(int index) {
		return fields[index];
	}

	public DataField get(String name) {
		int i = getFieldIndex(name);
		if (i != -1) {
			return fields[i];
		}

		return null;
	}

	public DataField[] getFields() {
		return fields;
	}

	public String getValue(int index) {
		DataField df = fields[index];
		if (df == null) {
			return null;
		}
		return df.getValue();
	}

	public String getValue(String name) {
		int i = getFieldIndex(name);
		if (i != -1) {
			return fields[i].getValue();
		}

		return null;
	}

	public String getFieldName(int index) {
		return definition.getField(index).getName();
	}

	public String[] getFieldNames() {
		String[] values = new String[definition.getFieldCount()];
		for (int i = 0; i < values.length; i++) {
			values[i] = getFieldName(i);
		}
		return values;
	}

	public int getFieldCount() {
		return fields.length;
	}

	public int getFieldIndex(String name) {
		int count = definition.getFieldCount();
		for (int i = 0; i < count; i++) {
			if (name.equalsIgnoreCase(getFieldName(i))) {
				return i;
			}
		}

		return -1;
	}

	// public DataField set(int index, DataField value) {
	// fields[index] = value;
	// return fields[index];
	// }

	public DataField set(int index, String value) {
		fields[index] = definition.getField(index).getParser().parse(value);
		return fields[index];
	}

	// public DataField set(String name, DataField value) {
	// int i = getFieldIndex(name);
	// if (i != -1) {
	// fields[i] = value;
	// return fields[i];
	// }
	//
	// return null;
	// }

	public DataField set(String name, String value) {
		int i = getFieldIndex(name);
		if (i != -1) {
			fields[i] = definition.getField(i).getParser().parse(value);
			return fields[i];
		}

		return null;
	}

	public DataRecord set(String[] fieldValues) {
		if (fields.length == 0) {
			fields = new DataField[fieldValues.length];
			definition.addFields(fieldValues.length);

			for (int i = 0; i < fields.length; i++) {
				set(i, fieldValues[i]);
			}
		} else if (fieldValues.length <= fields.length) {
			int i = 0;
			for (; i < fieldValues.length; i++) {
				set(i, fieldValues[i]);
			}

			for (; i < fields.length; i++) {
				set(i, null);
			}
		}

		return this;
	}

	public DataRecord set(Object[] fieldValues) {
		String[] newrow = new String[fieldValues.length];
		for (int i = 0; i < fieldValues.length; i++) {
			newrow[i] = (fieldValues[i] == null ? "" : fieldValues[i].toString());
		}

		return set(newrow);
	}

	public boolean isValid() {
		return errors == null || errors.size() == 0;
	}

	public List<String> getErrors() {
		return errors;
	}

	public void appendError(String message) {
		if (errors == null) {
			errors = new ArrayList<String>();
		}

		errors.add(message);
	}

	public void clearErrors() {
		errors = null;
	}

	public T getDefinition() {
		return definition;
	}

	public boolean equals(DataRecord obj) {
		DataField[] objfields = obj.getFields();
		if (objfields.length != this.fields.length) {
			return false;
		}

		for (int i = 0; i < objfields.length; i++) {
			DataField dataField = objfields[i];
			if (dataField != null && this.fields[i] == null) {
				return false;
			}

			if (dataField == null && this.fields[i] != null) {
				return false;
			}

			if (dataField != null && this.fields[i] != null && !dataField.equals(this.fields[i])) {
				return false;
			}
		}

		return true;
	}

	// public String toValue() {
	// StringBuffer content = new StringBuffer();
	//
	// if (fields.length > 0) {
	// char delimiter = ',';
	//
	// int max = fields.length - 1;
	// for (int i = 0; i < max; i++) {
	// if (fields[i] != null) {
	// content.append(fields[i].getValue());
	// } else {
	// content.append("");
	// }
	// content.append(delimiter);
	// }
	//
	// if (fields[max] != null) {
	// content.append(fields[max].getValue());
	// } else {
	// content.append("");
	// }
	// }
	//
	// return content.toString();
	// }
	//
	// public String toString() {
	// StringBuffer content = new StringBuffer();
	//
	// if (fields.length > 0) {
	// char delimiter = ',';
	//
	// int max = fields.length - 1;
	// for (int i = 0; i < max; i++) {
	// if (fields[i] != null) {
	// content.append(fields[i].toString());
	// } else {
	// content.append("");
	// }
	// content.append(delimiter);
	// }
	//
	// if (fields[max] != null) {
	// content.append(fields[max].toString());
	// } else {
	// content.append("");
	// }
	// }
	//
	// return content.toString();
	// }
}
